home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload Trio 2
/
Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO
/
dir24
/
morse111.zip
/
MORSE.ASM
< prev
next >
Wrap
Assembly Source File
|
1994-07-28
|
51KB
|
2,435 lines
name morse
kbright equ 1
kbleft equ 2
kbctrl equ 4
kbalt equ 8
kbscroll equ 10h
kbnum equ 20h
kbcaps equ 40h
kbins equ 80h
true equ 1
false equ 0
code SEGMENT public
assume cs:code,ds:code
org 100h
start: jmp transient
sound PROC near
;prequency is in bx
push ax
push dx
or bx,bx
jz sound_done ;frequency 0 no sound
mov ax,34ddh
mov dx,0012h
cmp dx,bx
jnb sound_done
div bx
mov bx,ax
in al,61h
test al,03h
jnz a
or al,03h
out 61h,al
mov al,0b6h
out 43h,al
a: mov al,bl
out 42h,al
mov al,bh
out 42h,al
sound_done:pop dx
pop ax
ret
sound endp
delay proc near
;duration is in cx
jcxz delay_done;no delay
delay_again:push cx
db 0b9h
timing dw 0 ;mov cx,timing
delay_again1:loop delay_again1
pop cx
loop delay_again
delay_done:ret
delay endp
nosound proc near
;turn off sound
push ax
in al,61h
and al,0fch
out 61h,al
pop ax
ret
nosound endp
beep proc near
;bx contains frequency and cx duration
push cx
call sound
call delay
call nosound
pop cx
ret
beep endp
uppercase proc near
;converts character in al to uppercase, otherwise unchanged
cmp al,'a'
jb exit_uppercase ;character is not lowercase
cmp al,'z'
ja exit_uppercase
sub al,32
exit_uppercase:ret
uppercase endp
char_out proc near
;character should be in al
PUSH BX
PUSH cX
PUSH DX
test byte ptr key_mode,kbalt
jz no_skip
cmp donotskip,false
jne no_skip
mov skip_line,true
jmp char_exit
no_skip:cmp al,0ah ;is character linefeed?
jne not_lf
jmp char_exit
not_lf:cmp al,0dh
jne not_cr
mov al,' '
mov prev_char,al
not_cr:MOV AH,AL ;save al
CMP AL,PREV_CHAR
JNE MULT0 ;not the same as previous character
OR AL,AL
JZ MULT0
CMP AL,'0'
JB MULT_CHAR;NOT A DIGIT
CMP AL,'9'
JBE MULT0 ;CHARACTER IS A DIGIT
MULT_CHAR:INC MULT ;character same as previous char
JMP CONTINUE_CHAR
MULT0:MOV MULT,0
CONTINUE_CHAR:MOV PREV_CHAR,AL
CMP MULT,1
Jbe test_for_space
jmp CHAR_EXIT
test_for_space:CMP AL,' '
JNE CONTINUE_CHAR1
SPACE_CHAR:MOV CX,DOT
CALL DELAY
JMP CHAR_EXIT
CONTINUE_CHAR1:MOV cX,STARTFREQ
mov dx,ditfreq
CMP AL,26
JA not_ctrl_char
;CHARACTER IS CONTROL A-Z
shr cx,1
SHR DX,1;divide freq by two
ADD AL,64;CHANGE CONTROL CHARACTER TO CORRESPONDING UPPERCASE CHARACTER
not_ctrl_char:CMP AL,97
JB not_lowercase_char
CMP AL,122
JA not_lowercase_char
SUB AL,32;CONVERT TO UPPERCASE
cmp practice,false
jne not_lowercase_char
CALL LO_FREQ ;make freq lower to identify lowercase
push dx
mov dx,cx
call lo_freq
mov cx,dx
pop dx
not_lowercase_char:CMP AH,91
JB CONTINUE_CHAR4
CMP AH,94
JE CONTINUE_CHAR4
cmp ah,'a'
jae continue_char4
CALL LO_FREQ
push dx
mov dx,cx
call lo_freq
mov cx,dx
pop dx
CONTINUE_CHAR4:CMP AH,123
JB CONTINUE_CHAR5
CMP AH,127
JA CONTINUE_CHAR5
SUB AL,26
cmp ah,127
je continue_char5
CALL LO_FREQ
call lo_freq
push dx
mov dx,cx
call lo_freq
call lo_freq
mov cx,dx
pop dx
CONTINUE_CHAR5:OR AH,AH
JZ CHAR_EXIT
CMP AH,27
JB CONTINUE_CHAR6
CMP AH,32
JB CHAR_EXIT
CONTINUE_CHAR6:CMP AH,128
JAE CHAR_EXIT
sub al,33; exclamation mark is first item in morse_array
xor bh,bh
mov bl,al
mov bl,morse_array[bx]
;bl contains the encoded morse character
char_start:cmp bl,1
jbe char_done
test bl,1
push bx;save encoded morse character
jz dash
mov bx,DX
call sound
push cx
mov cx,dit
jmp char_a
dash:
mov bx,cX
call sound
push cx
mov cx,dot
char_a:call delay
call nosound
mov cx,weighting
call delay
pop cx
pop bx
shr bl,1
jmp char_start
char_done:;put delay between characters
mov cx,dot
call delay
CHAR_EXIT:POP DX
POP CX
POP BX
ret
char_out endp
LO_FREQ PROC NEAR
;takes frequency in dx, lowers it and returns freq in dx
PUSH AX
push bx
push cx
MOV CX,11
CMP AH, 123
JB LOWERCASE
MOV CL,13
LOWERCASE:
MOV AX,dX;frequency is in ax
xor dx,dx
DIV cX
MOV cX,10
MUL cX
MOV DX,AX
pop cx
pop bx
POP AX
RET
LO_FREQ ENDP
test_freq_range proc near
;new freq is in ax. if within range put in startfreq
jc exit_test
cmp ax,20
jb exit_test
cmp ax,10000
ja exit_test
mov startfreq,ax
mov ditfreq,ax
exit_test:ret
test_freq_range endp
test_speed_range proc near
;if speed in range then set wpm
jc test_speed_exit ;error occurred in read_decimal, invalid digit
cmp ax,3
jb test_speed_exit
cmp ax,100
ja test_speed_exit
mov words_per_min,ax
call set_speed_wpm
test_speed_exit:ret
test_speed_range endp
set_speed_wpm proc near
;set speed to words_per_min
push ax
push dx
mov ax,32000
xor dx,dx ;msw of divisor is 0
div words_per_min
mov dit,ax
mov weighting,ax
mov dx,3
mul dx
mov dot,ax
mov ax,words_per_min
mov weighting_wpm,ax
mov ratio_wpm,ax
pop dx
pop ax
ret
set_speed_wpm endp
set_weighting_wpm proc near
;sets weighting wpm, should normally be same as words_per_min
push ax
push dx
mov ax,32000
xor dx,dx ;msw of divisor is 0
div weighting_wpm
mov weighting,ax
pop dx
pop ax
ret
set_weighting_wpm endp
set_ratio_wpm proc near
;sets ratio wpm, should normally be same as words_per_min
push ax
push dx
mov ax,32000
xor dx,dx ;msw of divisor is 0
div ratio_wpm
mov dit,ax
pop dx
pop ax
ret
set_ratio_wpm endp
check_for_keypress proc near
mov ah,cs:get_key
inc ah ;is key available?
pushf
call dword ptr int16_save
jnz yes_key
clc
ret
yes_key:pushf
mov ah,cs:get_key
call dword ptr int16_save
stc
ret
check_for_keypress endp
sweep_frequency proc near
;sweeps prequency up with ctrl key and down with alt key
;outputs frequency when space is pressed.
or dl,dl
jne s1
mov bx,startfreq
je s2
s1:mov bx,ditfreq
s2:push bx
call sound ;sound concinuous tone
pop bx
sweep_loop:call check_for_keypress
jc exit_sweep_frequency ;key was pressed
test byte ptr key_mode,kbctrl
jz not_sweep_up
;control key is pressed so sweep up
inc bx
cmp bx,10000
jbe set_sweep_freq
mov bx,20
set_sweep_freq:push bx
call sound
pop bx
mov cx,6
call delay
not_sweep_up:test byte ptr key_mode,kbalt
jz sweep_loop
dec bx
cmp bx,20
jae set_sweep_freq
mov bx,10000
jmp set_sweep_freq
exit_sweep_frequency:or dl,dl
jne s3
mov startfreq,bx
mov ditfreq,bx
je s4
s3:mov ditfreq,bx
s4:call nosound
mov al,' '
call char_out ;put a space delay before decimal output
mov ax,bx
call output_decimal
ret
sweep_frequency endp
sweep_speed proc near
;select speed by pressing ctrl or alt
sweep_speed_start:
call check_for_keypress
jc sweep_speed_exit ;read the key and exit
mov bx,startfreq
mov cx,dot
call beep
mov cx,dit
call delay
test byte ptr key_mode,kbctrl
jz not_speed_up
cmp words_per_min,100
ja sweep_speed_start
inc words_per_min
call set_speed_wpm
not_speed_up:test byte ptr key_mode,kbalt
jz sweep_speed_start
cmp words_per_min,3
jbe sweep_speed_start
dec words_per_min
call set_speed_wpm
jmp sweep_speed_start
sweep_speed_exit:mov al,' '
call char_out ;put delay before wpm
mov ax,words_per_min
call output_decimal
ret
sweep_speed endp
sweep_weighting proc near
sweep_weighting_start:
call check_for_keypress
jc sweep_weighting_exit ;read the key and exit
mov bx,startfreq
mov cx,dot
call beep
mov cx,weighting
call delay
test byte ptr key_mode,kbctrl
jz not_weighting_up
cmp weighting_wpm,100
jae sweep_weighting_start
inc weighting_wpm
call set_weighting_wpm
not_weighting_up:test byte ptr key_mode,kbalt
jz sweep_weighting_start
cmp weighting_wpm,3
jbe sweep_weighting_start
dec weighting_wpm
call set_weighting_wpm
jmp sweep_weighting_start
sweep_weighting_exit:mov al,' '
call char_out
mov ax,weighting_wpm
call output_decimal
ret
sweep_weighting endp
sweep_ratio proc near
sweep_ratio_start:call check_for_keypress
jc sweep_ratio_exit ;read the key and exit
mov bx,startfreq
mov cx,dit
call beep
mov cx,weighting
call delay
test byte ptr key_mode,kbctrl
jz not_ratio_up
cmp ratio_wpm,100
jae sweep_ratio_start
inc ratio_wpm
call set_ratio_wpm
not_ratio_up:test byte ptr key_mode,kbalt
jz sweep_ratio_start
cmp ratio_wpm,3
jb sweep_ratio_start
dec ratio_wpm
call set_ratio_wpm
jmp sweep_ratio_start
sweep_ratio_exit:mov al,' '
call char_out
mov ax,ratio_wpm
call output_decimal
ret
sweep_ratio endp
sweep_timing proc near
sweep_timing_start:call check_for_keypress
jc sweep_timing_exit ;read the key and exit
mov bx,startfreq
mov cx,dot
call beep
mov cx,dit
call delay
test byte ptr key_mode,kbctrl
jz not_timing_up
cmp timing,1
jbe sweep_timing_start
dec timing
not_timing_up:test byte ptr key_mode,kbalt
jz sweep_timing_start
cmp timing,800h
jae sweep_timing_start
inc timing
jmp sweep_timing_start
sweep_timing_exit:mov al,' '
call char_out
mov ax,timing
call output_decimal
ret
sweep_timing endp
read_decimal proc near
;asciz string in ds:bx carry set if invalid decimal number
;returns decimal value in ax
push cx
push dx
push si
xor ax,ax ;start with 0
xor ch,ch
mov si,10
decimal_space:mov cl,[bx]
cmp cl,' '
jne decimal_loop ;nonspace character found
inc bx ;skip spaces at beginning
jmp decimal_space
decimal_loop:mov cl,[bx]
cmp cl,' '
jbe decimal_done ;end of string found
cmp cl,'0'
jb decimal_error
cmp cl,'9'
ja decimal_error
mul si
sub cl,'0'
add ax,cx
inc bx
jmp decimal_loop
decimal_done:clc
read_decimal_exit:pop si
pop dx
pop cx
ret
decimal_error:stc
jmp read_decimal_exit
read_decimal endp
input_string proc near
;reads up to a string_len character string from the keyboard
;stores asciz result in string_buffer
push ax
push bx
push cx
push si
mov bx,offset string_buffer
xor si,si
mov cx,si
get_input_character:call read_a_key
cmp al,0dh
je exit_input
cmp al,8 ;is character a backspace?
jne char_not_backspace
or cl,cl
jne not_beginning_input
push bx
push cx
mov bx,1500
mov cx,1000
call beep
pop cx
pop bx
jmp get_input_character
not_beginning_input:dec cl
dec si
jmp get_input_character
char_not_backspace:cmp cl,string_length
ja get_input_character
call uppercase
mov [bx+si],al
mov mult,0
call char_out
inc si
inc cl
cmp string_length,0
je exit_input
jmp get_input_character
exit_input:xor al,al
mov [bx+si],al
pop si
pop cx
pop bx
pop ax
ret
input_string endp
strpos proc near
;es:di point to main string
;ds:si point to substring
;es = ds int this program.
;returns position of substring in main in ax. Strings are assumed to be asciiZ strings.
push cx
push dx
cld ;move forward
;find length of main string
push di ;save start of main string
xor al,al ;scan for 0
mov cx,255 ;maximum length allowed
repne scasb
mov dx,254
sub dx,cx ;dx holds length of main string
mov cl,255 ;maximum length allowed
mov di,si ;put offset of substring in di
repne scasb
sub di,si
mov cx,di
dec cl ;cx contains length of substring
pop di ;restore offset of main
;if either string has 0 length, return 0
xor ax,ax
or dl,dl
jne main_not_zero
jmp strpos_exit ;main has 0 length
main_not_zero:or cl,cl
jz strpos_exit ;substring has 0 length
;length of substring should not be greater than length of main
cmp cl,dl
jbe lengths_ok
jmp strpos_exit
lengths_ok:sub dl,cl
inc dl ;limit search of main string
main_string_loop:cmp al,dl
jbe continue_main_string
xor ax,ax ;no match was found
jmp strpos_exit
continue_main_string:
push cx ;save length of substring
push di ;save main offset
push si ;save substring offset
add di,ax ;this is where search begins in main string
repe cmpsb
pop si
pop di ;restore offsets
pop cx ;restore length of substring
jz got_position
inc al
jmp main_string_loop
got_position:inc al
strpos_exit:pop dx
pop cx
ret
strpos endp
read_a_key proc near
get_a_key:mov ah,cs:get_key
pushf
call dword ptr int16_save
or al,al
jne got_a_key
pushf
call dword ptr int16_save;ignore function key
jmp get_a_key ;function key was removed, so get more input
got_a_key:ret
read_a_key endp
public vid_out
vid_out proc far
cmp cs:inuse,false
je int10_not_inuse
jmp exit_int10
int10_not_inuse:push ax
mov ax,ss
cmp ax,cs:stackseg
pop ax
jne int10_ss_ok
jmp exit_int10
int10_ss_ok:mov cs:inuse,true
mov cs:output_character,ax
mov cs:int10_ss_save,ss
mov cs:int10_sp_save,sp
;switch ss:sp to morse stack
mov ax,cs
mov ss,ax ;ss = cs
mov sp,cs:int10_sp
mov ax,cs:output_character
push ax
push bx
push cx
push dx
push di
push si
push bp
push ds
push es
mov bx,cs
mov ds,bx ;ds = cs
mov es,bx
cmp ah,2
jne not_setting_cursor
;application is setting cursor position
or dl,dl ;is application moving cursor to left margin?
jne not_left_margin ;no
mov left_margin,true
jmp int10_done
not_left_margin:mov left_margin,false
jmp int10_done
not_setting_cursor:cmp ah,9
je echo_character
cmp ah,14
je echo_character
;ah is unknown test int10_quiet
cmp int10_quiet,true
je int10_is_quiet
call output_hex_word
int10_is_quiet:jmp int10_done
echo_character:sti
mov dl,key_mode
and dl,0eh
cmp al,0dh
jne not_return
mov skip_line,false
mov left_margin,false
test dl,kbalt
jz not_return
call make_click
mov prev_char,' '
not_return:cmp dl,0eh
jne skip_quiet_toggle
xor byte ptr quiet_mode,true
skip_quiet_toggle:
cmp quiet_mode,true
jne not_in_quiet_mode
jmp int10_done
not_in_quiet_mode:cmp left_margin,true
jne same_line
mov skip_line,false ;new line
cmp prev_char,' '
je same_line
mov left_margin,0
mov cx,dot
shl cx,1 ;multiply by two
call delay
same_line:
mov cl,skip_char
add cl,skip_line
jne int10_done
cmp practice,false
je NORMAL_CHARACTER
;while in practice mode, all characters not defined in morse
;are skipped
cmp al,33
jb NORMAL_CHARACTER
; if character is !"#$%&'()*+ skip if in practice mode
cmp al,43
jbe int10_done
; if character is :;=<> skip if not in practice mode
cmp al,58
jb NORMAL_CHARACTER
cmp al,62
jbe int10_done
CMP AL,'@'
JE INT10_DONE
; if character is [\]^_ or accent skip if in practice mode
CMP AL,91
JB NORMAL_CHARACTER
CMP AL,96
JBE INT10_DONE
; if character is {|}~ skip if not in practice mode
CMP AL,123
JB NORMAL_CHARACTER
CMP AL,126
JBE INT10_DONE
NORMAL_CHARACTER:
cmp decimal,false
je no_decimal
xor ah,ah
call output_decimal
jmp int10_done
no_decimal:cmp hex,false
je no_hex
call output_hex_byte
jmp int10_done
no_hex:call char_out
int10_done:cli
pop es
pop ds
pop bp
pop si
pop di
pop dx
pop cx
pop bx
pop ax
mov ss,cs:int10_ss_save
mov sp,cs:int10_sp_save
mov cs:inuse,false
exit_int10: jmp dword ptr cs:int10_off_save
vid_out endp
output_decimal proc near
;converts ax to decimal number and
;outputs the result in morse or crt if config_flag is true
push cx
push dx
push si
xor cx,cx
mov si,10 ;divide by 10
get_digit:xor dx,dx ;set msw of divisor to 0
div si
add dl,30h ;convert to digit
push dx ;save digits so they can be output in reverse
inc cl
cmp ax,0
jz output_digit
jne get_digit
output_digit:pop ax ;get digit
cmp config_flag,false
je no_config
mov dl,al
mov ah,2
int 21h ;output character
jmp output_decimal_loop
no_config:test byte ptr key_mode,kbalt
jne output_decimal_loop
call char_out
output_decimal_loop:loop output_digit
cmp config_flag,true
je output_decimal_exit
mov al,' '
call char_out ;put space after last digit
output_decimal_exit:pop si
pop dx
pop cx
ret
output_decimal endp
output_hex_byte proc near
;outputs byte in al in hex
push cx
push ax
mov cl,4
shr al,cl
call output_hex_nibble
pop ax
and al,0fh
call output_hex_nibble
mov al,' '
call char_out
pop cx
ret
output_hex_byte endp
output_hex_nibble proc near
;outputs hex nibble in al
add al,30h
cmp al,'9'
jbe hex_out
add al,7
hex_out:call char_out
ret
output_hex_nibble endp
output_hex_word proc near
;outputs ax in hex
push cx
mov cl,12
word_loop:push ax
shr ax,cl
and al,0fh
call output_hex_nibble
pop ax
sub cl,4
jns word_loop
mov al,' '
call char_out
pop cx
ret
output_hex_word endp
public int9_in
int9_in proc far
pushf
call dword ptr cs:int9_off_save
cli
push ax
push es
mov ax,40h
mov es,ax
mov al,es:[17h]
mov cs:key_mode,al
pop es
in al,60h
mov cs:scan_code,ax
pop ax
iret
int9_in endp
public key_in
key_in proc far
cmp cs:inuse,false
jz int16_not_inuse
jmp exit_int16
int16_not_inuse:
push ax
mov ax,ss
cmp ax,cs:stackseg
pop ax
jne int16_stack_ok
jmp exit_int16
int16_stack_ok:
test ah,0fh
je switch_int16_stack
jmp exit_int16 ;application was not waiting to read a key
switch_int16_stack: ;application is waiting until key is pressed
mov cs:inuse,true
and ah,0f0h
mov cs:get_key,ah
mov cs:int16_ss_save,ss
mov cs:int16_sp_save,sp
;switch ss:sp to morse stack
mov ax,cs
mov ss,ax ;ss = cs
mov sp,cs:int16_sp
push ax
push bx
push cx
push dx
push di
push si
push bp
push ds
push es
mov bx,cs
mov ds,bx ;ds = cs
mov es,bx
is_key_in_buffer:
mov ah,cs:get_key
or ah,1
pushf
call dword ptr int16_save
jnz key_in_buffer
;no keys in buffer but scancode from int9 shows if
;any other key is pressed
cmp scan_code,46h ;scroll lock
jz got_scan
cmp scan_code,4ch ;cursor pad 5
jnz is_key_in_buffer
got_scan:mov extended,true ;non buffer key was pressed
mov ax,scan_code
jmp process_scan
key_in_buffer:
mov ah,cs:get_key
pushf
call dword ptr int16_save ;get the key
process_scan:cmp prefix,false ;has f10 already been pressed?
jz no_prefix ;no
mov prefix_code,ax ;store key after f10 was pressed
mov key_code,0
jmp process
no_prefix: ;f10 was not the previous key
mov key_code,ax
mov prefix_code,0 ;shows this key was not f10
process: call process_key
mov donotskip,false
mov skip_char,false
mov al,remove
add al,review_mode
or al,al
jz int16_done
mov remove,false
mov extended,false
jmp is_key_in_buffer
int16_done:pop es
pop ds
pop bp
pop si
pop di
pop dx
pop cx
pop bx
pop ax
mov ss,cs:int16_ss_save
mov sp,cs:int16_sp_save
mov cs:inuse,false
mov ax,cs:key_code
iret
exit_int16:jmp dword ptr cs:int16_save
key_in endp
process_key proc near
mov skip_line,false
mov skip_char,false ;DO NOT SKIP WHOLE LINES OR CHARACTERS
mov mult,0 ;ALWAYS OUTPUT THE CHARACTER REGARDLESS OF HOW MANY TIMES SAME
;KEY IS PRESSED
mov donotskip,true
cmp prefix,true
je prefix_on
jmp not_prefix
prefix_on:cmp review_mode,true
jz start_review_mode
jmp not_review_mode
start_review_mode:;AX CONTAINS PREFIX_CODE
cmp ah,1 ;escape
je esc_ins
cmp ah,52h
jne not_esc_ins
esc_ins:mov dx,cursor_pos
mov skip_char,true
call move_cursor ;put cursor back where it was when review was entered
mov skip_char,false
call output_exit
mov review_mode,false
mov found,false
mov prefix,false
jmp ret_1
not_esc_ins:mov dx,review_pos ;current review cursor position
CMP Al,9 ;TAB
JNE NOT_TAB
or dl,7
inc dl
cmp dl,79
jbe tab_line_ok
xor dl,dl ;left margin
inc dh ;next line
cmp dh,24
jbe tab_line_ok
call cursor_outof_range
xor dh,dh ;top line
tab_line_ok:mov review_pos,dx
mov skip_char,1
call move_cursor
mov skip_char,false
jmp ret_1
NOT_TAB:cmp ax,0f00h
jne not_shift_tab
test dl,7 ;is cursor already on a tab
jz sub_shift ;yes it was
and dl,0f8h
jmp shift_tab1
sub_shift:sub dl,8
shift_tab1:jns tab_line_ok
cmp dh,0
jne shift_line
call cursor_outof_range
mov dx,1848h ;lower rightmost tab
jmp tab_line_ok
shift_line:dec dh
mov dl,72
jmp tab_line_ok
not_shift_tab:cmp ah,48h
jne not_review_up
cmp dh,0
jne up_line
call cursor_outof_range
jmp report_review_character
up_line:dec dh
report_review_character:mov review_pos,dx
mov find_pos,dx
call move_cursor
jmp ret_1
not_review_up:cmp ah,50h
jne not_review_down
cmp dh,24
jb down_line
call cursor_outof_range
jmp report_review_character
down_line:inc dh
jmp report_review_character
not_review_down:cmp ah,4bh
jne not_review_left
cmp dl,0
jne left_line
call cursor_outof_range
jmp report_review_character
left_line:dec dl
jmp report_review_character
not_review_left:cmp ah,4dh
jne not_review_right
cmp dl,79
jb right_line
call cursor_outof_range
jmp report_review_character
right_line:inc dl
jmp report_review_character
not_review_right:cmp ah,47h
jne not_review_home
xor dx,dx
mov found,false
jmp report_review_character
not_review_home:CMP AH,49H
JNE NOT_REVIEW_PAGE_UP
XOR DH,DH
JMP REPORT_REVIEW_CHARACTER
NOT_REVIEW_PAGE_UP:CMP AH,51H
JNE NOT_REVIEW_PAGE_DOWN
MOV DH,24
JMP REPORT_REVIEW_CHARACTER
NOT_REVIEW_PAGE_DOWN:CMP AH,77H
JNE NOT_REVIEW_CTRL_HOME
XOR DL,DL ;BEGINNING OF CURRENT LINE
JMP REPORT_REVIEW_CHARACTER
NOT_REVIEW_CTRL_HOME:CMP AH,4FH
JNE NOT_REVIEW_END
MOV DX,1800H ;BOTTOM LEFT
JMP REPORT_REVIEW_CHARACTER
NOT_REVIEW_END:CMP AH,75H
JNE NOT_REVIEW_CTRL_END
MOV DL,79 ;FAR RIGHT OF CURRENT LINE
JMP REPORT_REVIEW_CHARACTER
NOT_REVIEW_CTRL_END:CMP AH,73H
JNE NOT_REVIEW_CTRL_LEFT
;MOVE TO PREVIOUS WORD
MOV SKIP_CHAR,TRUE ;DON'T OUTPUT CHARACTERS UNTIL PREVIOUS WORD IS FOUND
CALL FIND_PREVIOUS_WORD
JC FIND_WORD_ERROR
JMP FIND_WORD_OK
NOT_REVIEW_CTRL_LEFT:CMP AH,74H
JNE NOT_REVIEW_CTRL_RIGHT
;MOVE TO NEXT WORD
MOV SKIP_CHAR,TRUE ;DON'T OUTPUT CHARACTERS UNTIL NEXT WORD IS FOUND
CALL FIND_NEXT_WORD
JC FIND_WORD_ERROR
FIND_WORD_OK:MOV SKIP_CHAR,0
JMP REPORT_REVIEW_CHARACTER
FIND_WORD_ERROR:MOV BX,2000
MOV CX,2000
CALL BEEP
MOV DX,REVIEW_POS
CALL MOVE_CURSOR
JMP RET_1
NOT_REVIEW_CTRL_RIGHT:cmp al,'?'
jne not_question
jmp find
not_question:;test for a function key
push ax
mov bx,fkey_type
sub ah,fkey_offset[bx]
CMP AH,3BH
JB NOT_REVIEW_F_KEYS
CMP AH,43H
JBE GOT_REVIEW_F_KEYS
NOT_REVIEW_F_KEYS:pop ax
call uppercase
cmp al,'A'
jb not_ay
cmp al,'Y'
ja not_ay
sub al,65
mov dh,al
xor dl,dl
mov review_pos,dx
call review_line
xor dl,dl
mov skip_char,true
call move_cursor
jmp ret_1
not_ay:JMP RET_1
GOT_REVIEW_F_KEYS:pop ax
mov key_code,ax
jmp not_prefix
not_review_mode:cmp ah,1
jne not_escape1
call output_exit
mov prefix,false
jmp ret_1
not_escape1:
CMP AH,52H
JNE NOT_INSERT_KEY
MOV BX,OFFSET REVIEW_MODE_MESSAGE
CALL OUTPUT_MORSE_STRING
CALL GET_CURSOR_POSITION
MOV CURSOR_POS,DX
MOV REVIEW_POS,DX
MOV REVIEW_MODE,TRUE
JMP RET_1
NOT_INSERT_KEY:cmp f10_twice,true
jne not_f10_twice
mov f10_twice,false
mov prefix,false
mov remove,false
mov key_code,ax
ret
not_f10_twice:cmp al,'\'
jne not_toggle_quiet
xor byte ptr quiet_mode,true
jz quiet_exit
mov al,127
call char_out
quiet_exit:mov prefix,false
mov remove,true
ret
not_toggle_quiet:call uppercase
cmp al,'S'
jne not_speed1
call sweep_speed
jmp ret_1
not_speed1:cmp al,'K'
jne not_type
mov bx,offset type_message
call output_morse_string
type_loop:call read_a_key
cmp al,27
je type_done
mov mult,0
call char_out
jmp type_loop
type_done:call output_exit
jmp ret_1
not_type:cmp al,'F'
jne not_freq1
xor dl,dl
call sweep_frequency
jmp ret_1
not_freq1:cmp al,'D'
jne not_freq2
mov dl,1
call sweep_frequency
jmp ret_1
not_freq2:cmp al,'W'
jne not_weighting1
call sweep_weighting
jmp ret_1
not_weighting1:cmp al,'R'
jne not_ratio1
call sweep_ratio
not_ratio1:cmp al,'T'
jne not_timing1
call sweep_timing
jmp ret_1
not_timing1:cmp al,'I'
jne not10
xor byte ptr int10_quiet,true
jne not10
mov bx,1500
mov cx,1000
call beep
jmp ret_1
not10:cmp al,'='
jne not_equal
inc fkey_type
and fkey_type,3
cmp fkey_type,0
ja not_normal
mov bx,offset normal_message
jmp output_state
not_normal:cmp fkey_type,1
ja not_ctrl
mov bx,offset ctrl_message
jmp output_state
not_ctrl:cmp fkey_type,2
ja not_shift
mov bx,offset shift_message
jmp output_state
not_shift:mov bx,offset alt_message
output_state:call output_morse_string
jmp ret_1
not_equal:cmp al,'?'
je find
jmp not_find
find:
mov bx,2500
mov cx,1000
call beep
cmp found,true
je skip_find_beep
mov bx,2000
mov cx,1000
call beep
skip_find_beep:cmp review_mode,false
jne find_review_on
;review is off so find cursor position
call get_cursor_position
mov cursor_pos,dx ;store current cursor position
mov review_pos,dx ;review_pos = cursor_pos
mov find_pos,dx
mov review_mode,true ;turn on review mode
find_review_on:cmp found,true
je find_initialized ;the previous find was successful
mov dx,review_pos
mov find_pos,dx
mov string_length,40
call input_string
lea bx,string_buffer
cmp byte ptr [bx],0
jnz find_initialized ;don't search for a null string
jmp ret_1
find_initialized:mov dx,find_pos
cmp dh,24
ja find_done ;have searched all the screen
call store_screen_line
lea si,string_buffer
lea di,line_string
call strpos
or al,al ;did we find a match?
jz no_find_match ;substring not found in line dh
dec al
add find_pos,ax ;get cursor position of match
mov skip_char,false
mov dx,find_pos
mov review_pos,dx
call move_cursor
inc find_pos ;the next find won't get the same occurrance
mov found,true
jmp ret_1
no_find_match:inc dh ;try next line
xor dl,dl
mov find_pos,dx
mov ax,20
mov cl,dh
xor ch,ch
push dx
mul cx
pop dx
add ax,600
mov bx,ax
mov cx,150
call beep
jmp find_initialized
find_done:mov found,false
mov dx,review_pos
mov skip_char,true
call move_cursor
not_find:
comment `
$1f: begin {output scancode}
pre_code := 0; scan_code := 0;
while scan_code <>1 do
begin
if scan_code <128 then
begin
if scan_code <> pre_code then
begin
hex(scan_code);
line_out(temp);
end;
pre_code := scan_code;
inline($b4/$01/$9c/$2e/$ff/$1e/joff_key/$74/$08);
inline($b4/$00/$9c/$2e/$ff/$1e/joff_key);
end;
end; {while}
remove := true; prefix := false;
end; {output scan_code}
else
prefix := false; remove := true; exit;
end; {case review is false}
end; {f10 is false}
end; {if prefix}
`
not_prefix:
mov ax,key_code
cmp al,8
jne not_backspace
move_left:call get_cursor_position
cmp dl,0
je beginning_of_line
dec dl
call move_cursor
mov skip_char,true
inc dl
beginning_of_line:call move_cursor
mov skip_line,true
mov skip_char,true
ret
not_backspace:
cmp ax,2000h
jne not_ctrl_alt_d
test byte ptr key_mode,4
je not_ctrl_alt_d
call remove_morse
ret
not_ctrl_alt_d: cmp ah,48h ;cursor up
jne not_up
call get_cursor_position
cmp dh,0
je no_move_up
dec dh
call move_cursor
inc dh
mov skip_char,true
no_move_up:call move_cursor
ret
not_up:cmp ah,50h ;cursor down
jne not_down
call get_cursor_position
cmp dh,24
jae no_move_down
inc dh
call move_cursor
dec dh
mov skip_char,true
no_move_down:call move_cursor
ret
not_down:cmp ah,4bh
je move_left
cmp ah,4dh ;cursor right
jne not_right
call get_cursor_position
cmp dl,79
jae no_move_right
inc dl
call move_cursor
dec dl
mov skip_char,true
no_move_right:call move_cursor
ret
not_right:cmp ah,52h
jne not_insert
test byte ptr key_mode,80h
je not_insert
mov bx,offset insert_message
call output_morse_string
not_insert:mov bx,fkey_type
sub ah,fkey_offset[bx]
cmp ah,3bh
jne not_f1
mov bx,offset speed_message
call output_morse_string
mov string_length,3
call input_string
mov bx,offset string_buffer
call read_decimal
jnc change_speed
mov bx,offset decimal_error_message
call output_morse_string
jmp ret_1
change_speed:call test_speed_range
jmp ret_1
not_f1:cmp ah,3ch
jne not_f2
mov bx,offset frequency_message
call output_morse_string
mov string_length,5
call input_string
mov bx,offset string_buffer
call read_decimal
jnc change_freq
mov bx,offset decimal_error_message
call output_morse_string
jmp ret_1
change_freq:call test_freq_range
jmp ret_1
not_f2:cmp ah,3dh
jne not_f3
mov cl,1
xor decimal,cl ;toggle decimal
jz ret_1
MOV PRACTICE,0
MOV HEX,0
MOV BX,OFFSET DECIMAL_MESSAGE
CALL OUTPUT_MORSE_STRING
ret_1:mov remove,true
ret
not_f3:cmp ah,3eh
jne not_f4
mov cl,1
xor practice,cl ;toggle practice mode
JZ RET_1
MOV DECIMAL,0
MOV HEX,0
MOV BX,OFFSET PRACTICE_MESSAGE
CALL OUTPUT_MORSE_STRING
JMP RET_1
not_f4:cmp ah,3fh
jne not_f5
mov cl,1
xor hex,cl ;toggle hex mode
JZ RET_1
MOV PRACTICE,0
MOV DECIMAL,0
MOV BX,OFFSET HEX_MESSAGE
CALL OUTPUT_MORSE_STRING
JMP RET_1
not_f5:cmp ah,40h
je f6_f7
cmp ax,4100h
jne not_f6_f7
f6_f7:call get_cursor_position
mov cursor_pos,dx
cmp ah,41h
je start_review
xor dl,dl ;start at beginning of line
start_review:call review_line
mov dx,cursor_pos
mov review_pos,dx
mov skip_char,true
call move_cursor
jmp ret_1
not_f6_f7:
cmp ah,42h
jne not_f8
call get_cursor_position
mov al,'L'
call char_out
mov al,dh
inc al
xor ah,ah
call output_decimal
mov al,'C'
call char_out
mov al,dl
inc al
xor ah,ah
call output_decimal
call move_cursor
jmp ret_1
not_f8:cmp ah,43h
jne not_f9
mov bx,offset linexy_message
call output_morse_string
mov string_length,0
call input_string
call get_cursor_position
mov cursor_pos,dx
mov al,string_buffer
cmp al,'A'
jb not_f9
cmp al,'Z'
ja not_f9
sub al,'A'
mov dh,al
xor dl,dl
mov review_pos,dx
call review_line
mov skip_char,true
mov dx,cursor_pos
call move_cursor
jmp ret_1
not_f9:cmp ah,44h
jne not_f10
mov prefix,true
mov bx,2500
mov cx,1500
call beep
jmp ret_1
not_f10:
comment `
if no_mode and (key_code and 255 >0) then char_out(key_code);
end;{proc_key}
`
ret
process_key endp
output_exit proc near
mov bx,offset exit_message
call output_morse_string
ret
output_exit endp
review_line proc near
review_line_start:
test byte ptr key_mode,kbalt
jne review_line_exit
call move_cursor
inc dl
cmp dl,80
jl review_line_start
review_line_exit:ret
review_line endp
FIND_NEXT_WORD PROC NEAR
CALL MOVE_CURSOR
CMP AL,' '
JE GET_NEXT_WORD ;GET THE NEXT WORD OR COME TO THE END OF THE SCREEN
SKIP_CURRENT_WORD:;SKIP THE CURRENT WORD
INC DL ;MOVE TO THE RIGHT
CMP DL,79 ;IS CURSOR POSITION VALID FOR THIS LINE
JB SKIP_SAME_LINE
CMP DH,24
JAE FIND_next_ERROR ;END OF SCREEN
INC DH ;MOVE TO NEXT LINE
XOR DL,DL ;TO THE LEFT MARGIN
SKIP_SAME_LINE:CALL MOVE_CURSOR
CMP AL,' ' ;IF CHAR IS NOT A SPACE THEN WE ARE STILL IN CURRENT WORD
JNE SKIP_CURRENT_WORD ;CONTINUE TO READ CURRENT WORD
GET_NEXT_WORD:INC DL
CMP DL,79
JBE SAME_NEXT_LINE
CMP DH,24
JAE FIND_next_ERROR ;ALREADY AT LOWER RIGHT CORNER
INC DH
XOR DL,DL ;MOVE TO THE LEFT ON NEXT LINE
SAME_NEXT_LINE: CALL MOVE_CURSOR
CMP AL,' '
JE GET_NEXT_WORD
CLC ;INDICATE NO ERROR
RET
FIND_next_ERROR:STC ;ERROR
RET
FIND_NEXT_WORD ENDP
FIND_PREVIOUS_WORD PROC NEAR
mov got_word,false
cmp dl,0
jne same_prev_line
cmp dh,0
je find_previous_error
dec dh
mov dl,80
same_prev_line:mov skip_char,true;
r1:dec dl ;go left 1
call move_cursor
cmp al,' '
je no_word
mov got_word,true
no_word:cmp dl,0
jNE same_prev_line1
cmp got_word,true
je exit_r1
cmp dh,0
je find_previous_error
dec dh
mov dl,80
jmp r1
same_prev_line1:cmp got_word,false
je r1
cmp al,' '
je exit_r1
jmp r1
exit_r1:cmp al,' '
jne back_word
inc dl
back_word:mov skip_char,false
clc
ret
find_previous_error:stc
ret
FIND_PREVIOUS_WORD ENDP
get_cursor_position proc near
;returns cursor position in dx
push ax
mov ah,0fh
pushf
call dword ptr int10_off_save
mov ah,3
pushf
call dword ptr int10_off_save
pop ax
ret
get_cursor_position endp
move_cursor proc near
;moves cursor to position in dx and outputs character
push dx
mov ah,0fh
pushf
call dword ptr int10_off_save
pop dx
mov ah,2
pushf
call dword ptr int10_off_save ;move cursor
mov ah,8
pushf
call dword ptr int10_off_save
cmp skip_char,false
je output_move_cursor
ret
output_move_cursor:cmp decimal,false
je output_cursor_1
xor ah,ah
jmp output_decimal
output_cursor_1:cmp hex,false
jz output_cursor_2
jmp output_hex_byte
output_cursor_2:jmp char_out
move_cursor endp
cursor_outof_range proc near
mov bx,2500
mov cx,200
call beep
ret
cursor_outof_range endp
store_screen_line proc near
;stores line in string_buffer starting at cursor position in dx
push dx
push di
cld ;move forward
mov skip_char,true ;so character won't be output when move_cursor is called
lea di,line_string ;where screen line will go
store_screen_loop:call move_cursor
call uppercase
stosb
cmp dl,79
jae store_screen_exit ;line is complete
inc dl
jmp store_screen_loop
store_screen_exit:xor al,al
stosb ;terminate string with null
pop di
pop dx
call move_cursor ;restore cursor to original position
mov skip_char,false
ret
store_screen_line endp
make_click proc near
cmp click_flag,true
jne no_click
mov bx,1500
mov cx,80
call beep
no_click:ret
make_click endp
output_morse_string proc near
;outputs asciiz string in morse using char_out
;string is in ds:bx
push ax
string_loop:cmp fkey_type,3
je skip_alt_test
test byte ptr key_mode,kbalt
jne string_done
skip_alt_test:mov al,[bx]
cmp al,20h
jb string_done
call char_out
inc bx
jmp string_loop
string_done:pop ax
ret
output_morse_string endp
output_string proc near
;outputs asciiz string to int10_off_save
push ax
push si
mov si,bx
string_loop1:mov al,[si]
cmp al,0
je string_done1
mov ah,0eh
pushf
call dword ptr int10_off_save
inc si
jmp string_loop1
string_done1:pop si
pop ax
ret
output_string endp
remove_morse proc near
;attempts to remove morse program from memory, saves rebooting
cli
push ax
mov al,127
call char_out
mov ax,cs
mov es,ax ;sets es = cs
mov ax,4900h
int 21h ;free memory allocated for morse
jnc remove_ok ;no error occurred
;remove error
mov bx,offset remove_error_message
call output_string
xor dl,dl
mov cx,1000
beep1_loop:mov bx,1000
call beep
mov bx,1500
call beep
inc dl
cmp dl,5
jb beep1_loop
jmp remove_exit
remove_ok:
mov bx,offset remove_ok_message
call output_string
remove_exit:push ds
lds dx,dword ptr int10_off_save
mov ax,2510h
int 21h ;restore int 10h vector
lds dx, dword ptr cs:int16_save ;remember ds was changed
mov ax,2516h
int 21h ;restore int 16h vector
lds dx,dword ptr cs:int9_off_save ;remember ds was changed
mov ax,2509h
int 21h ;restore int 16h vector
pop ds
pop ax
push ds
pop es
int 20h ;exit to dos
remove_morse endp
public morse_array,dit,dot,startfreq,prev_char,mult,practice,paragraphs,inuse
public output_character,stackseg,skip_line,skip_char,args_start
public int10_seg_save,int10_off_save,int16_save,int9_seg_save
public int9_off_save
public int10_ss_save,int10_sp_save,int16_ss_save,int16_sp_save,int9_ss_save
public int9_sp_save
public int9_sp,int10_sp,int16_sp
resident_variables label byte
morse_array db 52h,24h,28h,7fh,10h,13h,9ch,29h,2dh,35h,2ch,4ch,2eh,55h,36h,20h,21h,23h ;=50
db 27h,2fh,3fh,3eh,3ch,38h,30h,33h,31h,41h,18h,60h,73h,37h,5h,1eh,1ah,0eh,3h,1bh ;=70
db 0ch,1fh,7h,11h,0ah,1dh,4h,6h,8h,19h,14h,0dh,0fh,2h,0bh,17h,9h,16h,12h,1ch ;=90
db 29h,36h,2dh,3dh,2eh,37h,29h,17h,2Dh,3Dh,57h
dit dw 2000
dot dw 6000
weighting dw 2000
weighting_wpm dw 16
ratio_wpm dw 16
startfreq dw 1000;default frequency
ditfreq dw 1000
words_per_min dw 16
PRACTICE dB false
decimal db false
hex db false
f10_twice db false
fkey_type dw 0
fkey_offset db 0,35,25,45
click_flag db true
get_key db 0
mult db 0
PREV_CHAR DB 0
got_word db ?
output_character dw ?
cursor_pos dw ?
find_pos dw ?
review_pos dw ?
remove_ok_message db 'Morse program has been removed from memory',0dh,0ah,0
insert_message db 'INS',0
normal_message db 'NORMAL',0
alt_message db 'ALT',0
ctrl_message db 'CTRL',0
shift_message db 'SHIFT',0
linexy_message db 'A-Y?',0
speed_message db 'SPEED?',0
frequency_message db 'FREQ?',0
DECIMAL_MESSAGE DB 'DEC',0
HEX_MESSAGE DB 'HEX',0
PRACTICE_MESSAGE DB 'prac',0
decimal_error_message db 'ERROR',0
type_message db 'TYPE',0
string_length db ?
string_buffer db 81 dup(?)
line_string db 81 dup(?)
remove_error_message db 'An error occurred while removing morse program. '
db 'Reboot system',0dh,0ah,0
int10_off_save dw ?
int10_seg_save dw ?
int10_quiet db true
int16_save dw ?,?
int9_off_save dw ?
int9_seg_save dw ?
int10_sp_save dw ?
int10_ss_save dw ?
int16_sp_save dw ?
int16_ss_save dw ?
int9_sp_save dw ?
int9_ss_save dw ?
int9_sp dw ?
int10_sp dw ?
int16_sp dw ?
paragraphs dw ?
stackseg dw ?
inuse db 0
key_code dw 0
scan_code dw 0
prefix_code dw 0
prefix db 0
extended dw 0
remove db 0
review_mode db false
key_mode db 0
quiet_mode db false
REVIEW_MODE_MESSAGE DB 'RVU',0
exit_message db 'EXIT',0
found db false
skip_line db false
skip_char db false
donotskip db false
left_margin db 0
transient proc near
;save old interrupt vectors
mov ax,3509h
int 21h
mov int9_off_save,bx
mov int9_seg_save,es
mov ax,3510h
int 21h
mov int10_off_save,bx
mov int10_seg_save,es
mov ax,3516h
int 21h
mov int16_save,bx
mov int16_save[2],es
mov ax,351ch
int 21h
mov int1c_off_save,bx
mov int1c_seg_save,es
push ds
pop es ;make es = ds
call get_args
cmp cx,1
jae set_arg_freq
jmp skip_args ;no arguments were given
set_arg_freq:mov bx,args_start[0] ;offset for first arguement
mov al,[bx] ;get first character of first argument
call uppercase
cmp al,'A'
jb got_freq_arg
cmp al,'C'
jne not_config
mov config_flag,true
jmp skip_args
not_config:cmp al,'H'
jne not_help
call output_help
not_help:inc bl ;point to next character
mov skip_greeting,true ;don't display copyright
cmp al,'S'
je got_freq_arg
xor ah,ah
mov al,[bx] ;should be a digit
sub al,30h
cmp al,2
jae keepres_ok
mov al,2
keepres_ok:
mov keepres_arg,ax
inc bl
got_freq_arg:
call read_decimal
call test_freq_range
cmp cx,2
jb skip_args
cmp keepres_arg,2
je skip_args
mov bx,args_start[2]
call read_decimal
call test_speed_range
cmp cx,3
jb skip_args
cmp keepres_arg,3
je skip_args
mov bx,args_start[4]
call read_decimal
mov weighting_wpm,ax
call set_weighting_wpm
cmp cx,4
jb skip_args ;no ratio
cmp keepres_arg,4
je skip_args
mov bx,args_start[6]
call read_decimal
mov ratio_wpm,ax
call set_ratio_wpm
cmp cx,5
jb skip_args ;no timing
cmp keepres_arg,5
je skip_args
mov bx,args_start[8]
call read_decimal
mov timing,ax
skip_args:
cmp skip_greeting,true
je transient_continue
mov dx,offset copyright_message
mov ah,9
int 21h
transient_continue:
cmp timing,0
jne skip_set_timing
;find timing using int 1c
mov ax,251ch
mov dx,offset set_timing
int 21h
xor dx,dx ;start with 0
timing_loop:cmp timer,0
je timing_loop ;wait for first 1c interrupt before continuing
mov cx,0310h ;determined by trial and error to give proper timing value
timing_loop1:
cmp timer,1
ja exit_timing
loop timing_loop1
inc dx
jmp timing_loop
exit_timing:mov timing,dx
push ds
mov dx,cs:int1c_off_save
mov ax,cs:int1c_seg_save
mov ds,ax
mov ax,251ch
int 21h ;restore int 1ch vector
pop ds
skip_set_timing:
cmp config_flag,false
je no_config1
call configure_morse
no_config1:cmp word ptr keepres_arg,0
je make_resident
mov bx,keepres_arg
dec bx ;relative to zero
shl bx,1 ;times two to index array
mov bx,args_start[bx]
call output_morse_string
int 20h
make_resident:
mov bx,offset transient ;find where code ends
test bx,15 ;is it in the middle of a paragraph
jz get_sp ;no
or bl,15
inc bx ;set bx to paragraph boundary
get_sp:add bx,512
mov stackseg,ss
mov int10_sp,bx
add bx,512
mov int16_sp,bx
add bx,256
mov int9_sp,bx
mov cl,4
shr bx,cl ;divide by 16 to get paragraphs
inc bx
mov paragraphs,bx
mov ax,4900h
mov bx,2ch
mov es,[bx] ;es = segment of environment
int 21h ;free environment
mov ax,2510h ;set interrupt 10h vector
mov dx,offset vid_out
int 21h
mov ax,2516h
mov dx,offset key_in
int 21h
mov ax,2509h
mov dx,offset int9_in
int 21h
mov ax,3100h
mov dx,paragraphs
int 21h ;terminate and stay resident
transient endp
get_args proc near
;stores arguement offsets into arg_start array
;returns the number of args in cx
xor bx,bx ;start with 0
mov al,[80h]
or al,al
jne args
jmp args_done ;0 length means no arguements
args:mov si,81h ;si = offset of first arguement
skip_arg_spaces: ;argument must begin with nonspace character
lodsb
cmp al,' '
je skip_arg_spaces
cmp al,0dh
je args_done
dec si ;si contains offset of current argument
mov args_start[bx],si
inc si
add bx,2
args_loop:lodsb
cmp al,0dh
je args_done ;found the end
cmp al,' '
jne args_loop
je skip_arg_spaces
args_done:shr bx,1
mov cx,bx
ret
get_args endp
set_timing proc near
inc cs:timer
jmp dword ptr cs:int1c_off_save
set_timing endp
configure_morse proc near
mov dx,offset configure_message
mov ah,9
int 21h
call read_a_key
cmp al,1bh
jne config_continue
int 20h
config_continue:
mov dx,offset crlf
mov ah,9
int 21h;go to next line
mov dx,offset filename
mov ah,3dh ;open handle
mov al,2;read/write
int 21h;open handle
jnc open_ok
mov ah,9
mov dx,offset open_error_message
int 21h
int 20h
open_ok:mov args_start,ax ;save handle
mov bx,ax
mov ax,4202h ;seek
xor cx,cx
xor dx,dx
int 21h ;seek to eof to get length of file
mov cx,offset end_of_segment
sub cx,100h ;subtract length of psp
cmp ax,cx ;must be = if file is proper length
je length_ok
bad_version:mov dx,offset bad_version_message
mov ah,9
int 21h
int 20h
length_ok: ;lengths are the same, now check version
mov dx,offset version_message
mov si,dx
sub dx,100h ;get actual file offset by subtracting length of psp
mov ax,4200h
xor cx,cx
int 21h ;seek to bersion_message
mov ah,3fh ;read
mov cx,4 ;bytes to read
mov dx,offset string_buffer
mov di,dx
int 21h
;compare the two versions which must be the same
mov bx,di
mov cl,4
repe cmpsb
jne bad_version
mov bx,offset minimum_freq
mov cx,startfreq ;get default value
call get_input_response
store_config_freq:mov startfreq,ax
mov ditfreq,ax
mov bx,offset minimum_speed
mov cx,words_per_min ;get default value
call get_input_response
mov words_per_min,ax
call set_speed_wpm ;sets dit, dot, ratio, ratio_wpm, weighting, weighting_wpm
mov bx,offset minimum_weighting
mov cx,weighting_wpm ;get default value
call get_input_response
mov weighting_wpm,ax
call set_weighting_wpm
mov bx,offset minimum_ratio
mov cx,ratio_wpm ;get default value
call get_input_response
mov ratio_wpm,ax
call set_ratio_wpm
mov bx,offset minimum_timing
mov cx,timing ;get default value
call get_input_response
mov timing,ax
mov dx,offset config_practice_message
mov cl,practice
call get_yn_response
mov practice,al
mov dx,offset config_click_message
mov cl,click_flag
call get_yn_response
mov click_flag,al
mov dx,offset config_fkey_message
mov ah,9
int 21h
mov ah,1
int 21h ;get a character
cmp al,'0'
jbe key_default
cmp al,'5'
jb got_key_type
key_default: mov al,'1'
got_key_type:
sub al,031h
xor ah,ah
cmp ax,fkey_type
je no_fkey_change
inc config_changed
no_fkey_change:mov fkey_type,ax
mov dx,offset config_translation_message
mov ah,9
int 21h
mov ah,1
int 21h
call uppercase
cmp al,'Y'
jne skip_modify_translation
call modify_t_table
skip_modify_translation:
cmp config_changed,0
jz config_exit ;no changes so don't write back to disk
mov dx,offset config_write_message
mov ah,9
int 21h
call read_a_key
cmp al,27
je config_exit ;escape was pressed
config_write:
config_write1:mov config_flag,false
mov config_changed,0
mov bx,args_start ;get file handle
xor dx,dx
xor cx,cx ;msw is 0
mov ax,4200h
int 21h ;seek to beginning of file
mov cx,offset end_of_segment
sub cx,100h ;number of bytes to write
push cx
mov dx,100h ;ds:dx points to memory location for write
mov ah,40h
int 21h ;write entire file back to disk
;the whole file was written because timing comes before resident_variables
pop cx
cmp cx,ax ;were the correct number of bytes written?
jne write_error
jnc write_ok
write_error:mov ah,9
mov dx,offset write_error_message
int 21h
int 20h
write_ok:mov ah,3eh
mov bx,args_start
int 21h ;close handle
mov dx,offset success_message
mov ah,9
int 21h
config_exit:int 20h ;return to dos
configure_morse endp
modify_t_table proc near
mov string_length,8
modify_t_loop:mov dx,offset mod_char_message
mov ah,9
int 21h
mov ah,1
int 21h
cmp al,26
jbe modify_t_loop ;skip control chars
cmp al,27
je modify_t_exit ;escape
cmp al,'!'
jb modify_t_loop
cmp al,128
jae modify_t_loop ;skip extended graphics chars
call uppercase
push ax
call char_out
mov mult,0
pop ax
mov bl,al
sub bl,33
cmp al,123
jb mod_continue
sub bl,26 ;lowercase same as upper
mod_continue:xor bh,bh
mov ah,9
mov dx,offset offset_message
int 21h
mov ax,bx
call output_decimal
mov ah,9
mov dx,offset letter_message
int 21h
mov ah,0ah
mov dx,offset string_length
mov si,dx
int 21h
mov cl,[si+1]
or cl,cl
jz modify_t_loop ;no characters were entered
inc si
xor ch,ch
add si,cx
mov dl,1
mod_loop:shl dl,1
cmp byte ptr [si],'.'
jne not_period
or dl,1
not_period:dec si
loop mod_loop
cmp dl,morse_array[bx]
je modify_t_loop
inc config_changed
mov morse_array[bx],dl
jmp modify_t_loop
modify_t_exit:ret
modify_t_table endp
get_input_response proc near
;bx contains offset of minimum value for variable
;cx contains default value for variable
;returns value to be placed in variable in ax
retry_input_response:mov dx,bx
add dx,4 ;offset of message
mov ah,9
int 21h ;display message
mov dx,offset default_message
mov ah,9
int 21h
mov ax,cx ;put default current value in ax
call output_decimal ;default value
mov dx,offset paren_message
mov ah,9
int 21h
mov dx,offset string_length
mov string_length,6
mov ah,0ah
int 21h ;get line of input
cmp string_buffer,0 ;is it a null string
jne got_input_string ;no, at least 1 character was entered
mov ax,cx ;variable left unchanged
ret
got_input_string:push bx
mov bx,offset string_buffer
inc bx ;skip byte containing length of string
call read_decimal
pop bx
jc response_error ;invalid integer was entered
;now test ax to see if it is in range
cmp ax,[bx] ;compare with minimum value
jb retry_input_response ;below minimum
cmp ax,[bx+2]
ja retry_input_response
inc config_changed ;valid integer in range was entered
ret
response_error:mov dx,offset response_error_message
mov ah,9
int 21h
jmp retry_input_response
get_input_response endp
get_yn_response proc near
mov ah,9
int 21h
mov dx,offset default_message
mov ah,9
int 21h
mov ah,9
cmp cl,false
jne say_yes
mov dx,offset no_message
je say_default
say_yes:mov dx,offset yes_message
say_default:int 21h
yn_response:mov ah,1
int 21h ;get 1 character response
call uppercase
cmp al,'Y'
je set_config_true
cmp al,0dh
jne not_config_default
mov al,cl ;leave variable unchanged
jmp no_config_change
not_config_default:cmp al,'N'
jne yn_response
mov al,false
je test_config_change
set_config_true:mov al,true
test_config_change:cmp al,cl
jz no_config_change
inc config_changed
no_config_change:ret
get_yn_response endp
output_help proc near
;clear screen and put cursor in upper left corner
mov ax,0600h
mov bx,7000h
xor cx,cx ;upper left corner
mov dx,184fh ;lower right
pushf
call dword ptr int10_off_save
xor dx,dx
mov skip_char,true
call move_cursor
mov dx,offset help_message
mov ah,9
int 21h
int 20h
output_help endp
;the following variables are transient data and are discarded if
;morse becomes a tsr
args_start dw 5 dup(0) ;beginning offset of each argument
int1c_off_save dw ?
int1c_seg_save dw ?
protect_mask db 0
config_changed db false
skip_greeting db false
timer db 0
help_message db 'Morse.com is a TSR program which echoes screen output in morse code.',0dh,0ah
db 'useage: morse [c][s][H][frequency] [speed] [ratio] [weighting] [timing]',0dh,0ah
db 'Frequency can range from 20 to 10,000HZ. Speed, weighting, and ratio',0dh,0ah
db 'ranges from 3 to 100 words per minute.',0dh,0ah
db 'Pressing the ALT key during morse output tells morse to skip the current',0dh,0ah
db 'line. Normal output resumes when you release the ALT key.',0dh,0ah
db 'ALT-CTRL-D Removes morse.com from memory without rebooting.',0dh,0ah
db '<F1> You are prompted for speed in morse.',0dh,0ah
db '<F2> You are prompted in morse to enter frequency.',0dh,0ah
db '<F3> <F4> and <F5> Toggles decimal, practice and hex mode respectively.',0dh,0ah
db '<F6> Output entire cursor line.',0dh,0ah
db '<F7> Output current line from the cursor to the right.',0dh,0ah
db '<F8> Output cursor position and character.',0dh,0ah
db '<F9> Output line A-Y in morse.',0dh,0ah
db '<F10> is used as the first key for the following commands:',0dh,0ah
db '\ Toggles quiet mode.',0dh,0ah
db 'F, S, R, W, T sweeps frequency, speed, ratio, weighting and timing',0dh,0ah
db '<INS> review mode. <ESC> to exit review mode.'
db '? Find mode.',0dh,0ah
db 'K Keyboard mode. <ESC> to exit.$'
copyright_message db 0dh,0ah,'BLINDOS/PC',0dh,0ah,'Version '
version_message db '1.11',0dh,0ah,'Copyright 1990-1994 by Randy Formenti N8KL',0dh,0ah,'$'
no_message db 'NO) $'
yes_message db 'YES) $'
configure_message db 0dh,0ah,'Morse configuration allows you to modify defaults',0dh,0ah
db 'for frequency, speed, weighting, ratio, timing, practice and clicks.',0dh,0ah
db 'The Morse default function keys and the morse translation table may also be',0dh,0ah
db 'modified.',0dh,0ah
db 'After configuration, MORSE may be run with these new defaults without command',0dh,0ah
db 'line arguments.',0dh,0ah
db 'Press <ESC> to abort or any other key to continue. $'
config_translation_message db 0dh,0ah,'Do you want to modify the Morse '
db 'translation table (Y/N) $'
mod_char_message db 0dh,0ah,'Enter character to modify <ESC> to exit: $'
config_fkey_message db 0dh,0ah,'Choose from the following:',0dh,0ah
db '1 - F1 through F10',0dh,0ah
db '2 - CTRL F1 through CTRL F10',0dh,0ah
db '3 - SHIFT F1 through SHIFT F10',0dh,0ah
db '4 - ALT F1 through ALT F10',0dh,0ah
db 'Enter your choice (Default is F1 through F10): $'
minimum_freq dw 20
maximum_freq dw 10000
config_freq_message db 0dh,0ah,'Enter frequency <20-10000>$'
minimum_speed dw 3
maximum_speed dw 100
config_speed_message db 0dh,0ah,'Enter speed <3-100>$'
minimum_weighting dw 3
maximum_weighting dw 100
config_weighting_message db 0dh,0ah,'Enter weighting <3-100>$'
minimum_ratio dw 3
maximum_ratio dw 100
config_ratio_message db 0dh,0ah,'Enter ratio <3-100>$'
minimum_timing dw 0
maximum_timing dw 8000h
config_timing_message db 0dh,0ah,'Enter timing <0-32767>$'
config_practice_message db 0dh,0ah,'Do you want practice mode on <Y/N>$'
config_click_message db 0dh,0ah,'Do you want clicks on? <Y/N>$'
default_message db ' (Default is $'
paren_message db ') $'
config_write_message db 0dh,0ah,'Press <ESC> to abort or any other key to'
db ' write changes to disk.$'
offset_message db 0dh,0ah,'Offset into translation table is $'
letter_message db 0dh,0ah,'Enter periods and dashes representing morse for '
db 'the character: $'
filename db 'MORSE.COM',0
crlf db 0dh,0ah,'$'
open_error_message db 'Unable to open morse.com',0dh,0ah,'$'
response_error_message db 0dh,0ah,'Invalid number$'
success_message db 0dh,0ah,'morse has been updated successfully',0dh,0ah,'$'
bad_version_message db 'Incorrect version.',0dh,0ah,'$'
write_error_message db 0dh,0ah,'Unable to write morse.com.$'
config_flag db false
keepres_arg dw 0
end_of_segment label byte
code ends
end start